package com.dynamic.mybatis.core.parser.xml;

import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.dynamic.mybatis.core.enums.*;
import com.dynamic.mybatis.core.exceptions.DmsDocumentException;
import com.dynamic.mybatis.core.exceptions.MyBatisExecutorException;
import com.dynamic.mybatis.core.exceptions.MybatisBuilderException;
import com.dynamic.mybatis.core.generator.AbstractMethod;
import com.dynamic.mybatis.core.generator.MapperMethod;
import com.dynamic.mybatis.core.metadata.*;
import com.dynamic.mybatis.core.mock.Mock;
import com.dynamic.mybatis.core.parser.NamespaceHelper;
import com.dynamic.mybatis.core.parser.field.DynamicMixedMappedStatementFieldParser;
import com.dynamic.mybatis.core.parser.xml.validator.MybatisXmlValidator;
import com.dynamic.mybatis.core.session.DynamicSqlSession;
import com.dynamic.mybatis.core.utils.*;
import org.apache.ibatis.builder.MapperBuilderAssistant;
import org.apache.ibatis.logging.Log;
import org.apache.ibatis.logging.LogFactory;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.mapping.SqlSource;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.xml.sax.SAXParseException;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @Description
 * @Author xs
 * @Date 2023/4/25 11:12
 */
public class DynamicMappedStatementParser extends DynamicBaseMappedStatementParser {
    private static final Log logger = LogFactory.getLog(DynamicMappedStatementParser.class);

    public DynamicMappedStatementParser(DynamicSqlSession dynamicSqlSession) {
        super(dynamicSqlSession);
    }

    public static void main(String[] args) {
        String a = "4264d6c638054d4fab9ed2b74123dc33.c7938c36c5df4030b177cb1bafb0c31c.selectPageTest";
        String b = "4264d6c638054d4fab9ed2b74123dc33.c7938c36c5df4030b177cb1bafb0c31c";
    }

    /**
     * 　* @Description: 单表SQL
     */
    public DynamicMappedStatementMixedResult validate(String tenantCode, String namespace, String dataSourceCodes, List<String> tables, List<String> methods, List<DynamicMappedStatement> slaveList) {
        String tempNamespace = NamespaceHelper.getRandomNamespace();
        DynamicMappedStatementMixedResult result = new DynamicMappedStatementMixedResult();
        List<DynamicMappedStatement> dmsList = null;
        Exception exception = null;
        try {
            //生成
            dmsList = parseSingleTableMappedStatement(dataSourceCodes, tenantCode, tempNamespace, tables, methods);
            //拷贝
            copyDynamicMappedStatement(dmsList, slaveList);
            result.setParserResults(dmsList);
        } catch (Exception e) {
            exception = e;
            e.printStackTrace();
        }
        if (CollectionUtils.isNotEmpty(dmsList)) {
            result.setSqlStatement(dmsList.stream().filter(dms -> StringUtils.isNotBlank(dms.getSqlStatement())).map(dms -> dms.getSqlStatement()).collect(Collectors.joining()));
        }
        return validateHandle(dynamicSqlSession, result, tenantCode, namespace, tempNamespace, dataSourceCodes, exception);
    }

    /**
     * 　* @Description: 自定义SQL
     */
    public DynamicMappedStatementMixedResult validate(String tenantCode, String namespace, String dataSourceCodes, String sqlStatement, List<DynamicMappedStatement> slaveList) {
        DynamicMappedStatementMixedResult result = new DynamicMappedStatementMixedResult();
        Exception exception = null;
        String tempNamespace = NamespaceHelper.getRandomNamespace();
        try {
            List<DynamicMappedStatement> masterList = parseMapperMappedStatement(tenantCode,tempNamespace,slaveList.get(0).getShortId(),sqlStatement);
            //拷贝
            copyIgnorePropertiesDynamicMappedStatement(masterList, slaveList);
            //解析出入参数
            DynamicMixedMappedStatementFieldParser fieldParser = dynamicSqlSession.getDynamicMappedStatementHelper().getMixedMappedStatementFieldParser();

            for (DynamicMappedStatement dms : masterList) {
                try {
                    fieldParser.parseMappedStatementField(dms);
                    dms.setDynamicDataSourceKeys(new String[]{dataSourceCodes});
                    //设置表名 TODO 可能存在跨库
                    setDynamicMappedStatementTables(dms,fieldParser.getTables(dms.getDynamicDataSourceKeys(),dynamicSqlSession));
                } catch (Exception e) {
                    logger.error("DynamicMappedStatement ["+dms.getId() + "] parse error.");
                    throw e;
                }
            }
            //拷贝
            copyDynamicMappedStatement(masterList, slaveList);
            //添加到dynamicSqlSession上下文中( 以便后续删除configuration DynamicMappedStatement 和 MappedStatement)
            resetDynamicMappedStatement(tempNamespace, masterList);
            if (masterList.size() == 1) {
                masterList.get(0).toBuilder().setSqlStatement(sqlStatement);
            }
            dynamicSqlSession.getDynamicMappedStatementHelper().addDynamicMappedStatement(masterList);
            result.setParserResults(masterList);
        } catch (Exception e) {
            exception = e;
            e.printStackTrace();
        }
        result.setSqlStatement(sqlStatement);
        return validateHandle(dynamicSqlSession, result, tenantCode, namespace, tempNamespace, dataSourceCodes, exception);
    }

    /**
     * 单表操作
     */
    public List<DynamicMappedStatement> parseSingleTableMappedStatement(String dataSourceKey, String tenantCode, String namespace, List<String> tableNames, List<String> mapperMethods) throws DocumentException {
        DynamicMixedMappedStatementFieldParser fieldParser = dynamicSqlSession.getDynamicMappedStatementHelper().getMixedMappedStatementFieldParser();

        List<MappedStatementTable> tables = fieldParser.getDatabaseMeta(dynamicSqlSession, dataSourceKey, tableNames.toArray(new String[tableNames.size()]));

        if (mapperMethods == null || mapperMethods.size() < 1) {
            mapperMethods = Stream.of(MapperMethod.values()).map(MapperMethod::name).collect(Collectors.toList());
        }
        List<DynamicMappedStatement> dmsList = new ArrayList<>();

        DynamicConfiguration dynamicConfiguration = (DynamicConfiguration) configuration;
        for (MappedStatementTable table : tables) {
            //(序列化深拷贝，防止fields内字段被更改)
            byte[] serializeFields = BeanUtils.serialize(table.getFields());

            for (String mapperMethod : mapperMethods) {
                AbstractMethod injectorMethod = AbstractMethod.getByMapperMethod(mapperMethod);
                if (injectorMethod == null) {
                    throw new MybatisBuilderException("addSingleTableMybatisPlusMappedStatement injectorMethod [" + mapperMethod + "] not find. ");
                }
                MapperBuilderAssistant assistant = new MapperBuilderAssistant(dynamicConfiguration, "");
                DynamicMappedStatement dms = injectorMethod.inject(tenantCode, namespace, assistant, table);
                dms.setAuth(Boolean.TRUE);
                if (StringUtils.isNotBlank(dataSourceKey)) {
                    dms.setDynamicDataSourceKeys(dataSourceKey.split(","));
                }
                //入参
                MappedStatementMetaField inputParameter = fieldParser.inputParameterFieldParser(BeanUtils.deserialize(serializeFields), dms, true);
                //出参
                MappedStatementMetaField outputParameter;
                if (dms.getCommandType() == CommandType.StandardCommand.SELECT) {
                    outputParameter = fieldParser.outputParameterFieldParser(BeanUtils.deserialize(serializeFields), dms, dynamicConfiguration.getMappedStatement(dms.getId()));
                } else {
                    outputParameter = fieldParser.outputParameterFieldParser(dms);
                }
                dms.toBuilder()
                        .setInputParameter(inputParameter)
                        .setInputParameterMock(Mock.mock(dms.getInputParameter().get(0)))
                        .setOutputParameter(outputParameter);
                dmsList.add(dms);
            }
        }
        dynamicSqlSession.getDynamicMappedStatementHelper().addDynamicMappedStatement(dmsList);
        return dmsList;
    }

    /**
     * 自定义SQL
     */
    public List<DynamicMappedStatement> parseMapperMappedStatement(String tenantCode,String namespace,String shortId, String script)  {
        List<DynamicMappedStatement> dynamicMappedStatements = new ArrayList<>();
        if (isXml(trimBlank(script))) {
            //校验
            validateXmlMapperBody(script, namespace);
            String xml = MybatisXmlValidator.buildXmlMapperBody(script, NamespaceHelper.getNamespace(tenantCode, namespace));
            dynamicMappedStatements.addAll(parseMapperXmlMappedStatement(tenantCode,namespace,xml));
            //解析SQL 生成mybatis的MappedStatement (数据库字段解析会用到MappedStatement)
            parseMapperXmlAddConfiguration(xml);
        }else {
            DynamicMappedStatement dms = new DynamicMappedStatement();
            dms.setTenantCode(tenantCode);
            dms.setNamespace(namespace);
            dms.setShortId(shortId);
            dms.setSqlStatement(script);
            dms.setResultType("map");
            dms.setReturnType(ReturnType.StandardReturnType.COLLECT);
            dynamicMappedStatements.add(dms);

            //SQL解析
            SqlSource sqlSource = createSqlSource(configuration, trimBlank(dms.getSqlStatement()), null);
            //初始化mappedStatement
            MappedStatement.Builder builder = new MappedStatement.Builder(configuration, dms.getId(), sqlSource, CommandType.getSqlCommandType(dms.getCommandType()));
            builder.resultMaps(parserResultMap(dms.getId(), dms.getResultType(), dms.getResultMap()));
            MappedStatement mappedStatement = builder.build();
            //将mappedStatement 加入mybatis上下文中
            configuration.addMappedStatement(mappedStatement);

            SqlCommandType sqlCommandType = mappedStatement.getSqlCommandType();
            if(sqlCommandType != null){
                dms.setCommandType(sqlCommandType.name());
            }
        }
        return dynamicMappedStatements;

    }

    /**
     * 自定义SQL
     */
    public List<DynamicMappedStatement> parseMapperXmlMappedStatement(String tenantCode,String namespace, String xml) {
        try {
            //解析SQL 生成DynamicMappedStatement
            return document4jParser(tenantCode,namespace, xml);
        } catch (Exception e) {
            if (e instanceof DmsDocumentException) {
                throw e;
            } else if (e instanceof SAXParseException) {
                SAXParseException saxException = (SAXParseException) e;
                throw new DmsDocumentException(e, e.getMessage(), saxException.getLineNumber(), saxException.getColumnNumber());
            } else {
                throw new DmsDocumentException(e);
            }
        }
    }

    protected DynamicMappedStatementMixedResult validateHandle(DynamicSqlSession dynamicSqlSession, DynamicMappedStatementMixedResult result, String tenantCode, String namespace, String tempNamespace, String dataSourceCodes, Exception exception) {
        if (result == null) {
            result = new DynamicMappedStatementMixedResult();
        }
        DynamicConfiguration configuration = ((DynamicConfiguration) dynamicSqlSession.getSqlSession().getConfiguration());
        //删除临时空间
        configuration.cleanTemporaryNamespace(NamespaceHelper.getNamespace(tenantCode, tempNamespace));
        List<DynamicMappedStatement> dmsList = result.getParserResults();
        List<String> existentDms = new ArrayList<>();

        dmsList = treeToArray(dmsList, true);
        result.setParserResults(dmsList);

        if (CollectionUtils.isNotEmpty(dmsList)) {
            for (DynamicMappedStatement dms : dmsList) {
                DynamicMappedStatement.Builder builder = dms.toBuilder()
                        .setNamespace(namespace)
                        .setTargetDataSourceKey(dataSourceCodes)
                        .setShortId(dms.getShortId());

                DynamicMappedStatement existent = configuration.getDynamicMappedStatement(NamespaceHelper.getDynamicMappedStatementId(tenantCode, namespace, dms.getShortId()));
                if (existent != null) {
                    builder.setUid(existent.getUid());
                    existentDms.add(existent.getShortId());
                }
                if (CollectionUtils.isNotEmpty(dms.getInputParameter()) && dms.getInputParameterMock() == null) {
                    List<MappedStatementMetaField> inputParameter = TreeUtil.toTree(dms.getInputParameter());
                    dms.setInputParameterMock(Mock.mock(inputParameter.get(0), dms.getCommandType()));
                }
            }
        }

        if (exception != null) {
            if (exception instanceof SAXParseException) {
                SAXParseException pe = (SAXParseException) exception;
                result.setMessage(exception.getMessage());
                result.setLineNumber(pe.getLineNumber());
                result.setColumnNumber(pe.getColumnNumber());
            } else if (exception instanceof DmsDocumentException) {
                DmsDocumentException pe = (DmsDocumentException) exception;
                result.setMessage(exception.getMessage());
                result.setLineNumber(pe.getLineNumber());
                result.setColumnNumber(pe.getColumnNumber());
            } else {
                result.setMessage(exception.getMessage());
            }
            if (StringUtils.isBlank(result.getMessage())) {
                result.setMessage(exception.getMessage());
            }
            result.setStatus(Alert.StandardAlert.error);
        } else if (existentDms.size() > 0) {
            result.setMessage(" " + existentDms.stream().collect(Collectors.joining("\t")) + " 已存在,提交将会覆盖。");
            result.setStatus(Alert.StandardAlert.warning);
        } else if (result.getStatus() == null) {
            result.setMessage("成功.");
            result.setStatus(Alert.StandardAlert.success);
        }
        return result;
    }

    public DynamicMappedStatementMixedResult parseMappedStatement(String mappedStatementId) {
        DynamicMappedStatement dms = dynamicSqlSession.getDynamicMappedStatementHelper().getDynamicMappedStatement(mappedStatementId);
        DynamicMappedStatementMixedResult mixedResult = new DynamicMappedStatementMixedResult();
        if (dms == null) {
            return mixedResult;
        }
        List<DynamicMappedStatement> dmsList = Collections.singletonList(dms);
        dmsList = treeToArray(dmsList, true);
        mixedResult.setParserResults(dmsList);
        if (CollectionUtils.isNotEmpty(dmsList)) {
            mixedResult.setSqlStatement(dmsList.stream().map(d -> d.getSqlStatement()).filter(StringUtils::isNotBlank).collect(Collectors.joining(System.lineSeparator())));
        }
        return mixedResult;
    }

    public List<DynamicMappedStatement> queryExpandMappedStatement(List<DynamicMappedStatement> dms) {
        if (CollectionUtils.isEmpty(dms)) {
            return Collections.EMPTY_LIST;
        }
        List<DynamicMappedStatement> dmsList = new ArrayList<>();
        for (DynamicMappedStatement dm : dms) {
            dmsList.addAll(treeToArray(Collections.singletonList(dm), true));
        }
        return dmsList;
    }

    /**
     * 　* @Description: 合并多个MappedStatement
     * 　* @param dmsList 和 dmsList元素属性DynamicMappedStatement.inputParameter 和 DynamicMappedStatement.outputParameter 为 Array结构
     */
    public DynamicMappedStatementMixedResult merge(String namespace, String sqlStatement, List<DynamicMappedStatement> dmsList) {

        DynamicMappedStatementMixedResult result = new DynamicMappedStatementMixedResult();
        if (CollectionUtils.isEmpty(dmsList)) {
            return result;
        }
        if (dmsList.size() > 1) {
            //合并后的跟节点
            DynamicMappedStatement dms = mergeDynamicMappedStatement(sqlStatement, namespace, dmsList);
            //将树形结构转换为数组
            result.setParserResults(treeToArray(Collections.singletonList(dms), false));
        } else {
            result.setParserResults(dmsList);
        }
        result.setSqlStatement(sqlStatement);
        result.setStatus(Alert.StandardAlert.success);
        result.setMessage("成功");

        return result;
    }

    /**
     * 　* @Description: 合并多个MappedStatement
     * 　* @param dmsList 和 dmsList元素属性DynamicMappedStatement.inputParameter 和 DynamicMappedStatement.outputParameter 为 Array结构
     * 　* @return ${return}
     */
    public DynamicMappedStatement mergeDynamicMappedStatement(String sqlStatement, String namespace, List<DynamicMappedStatement> dmsList) {
        int mergeIndex = -1;
        for (int i = 0; i < dmsList.size(); i++) {
            DynamicMappedStatement dms = dmsList.get(i);
            if (dms.getCommandType() == CommandType.StandardCommand.MERGE) {
                mergeIndex = i;
                break;
            }
        }
        DynamicMappedStatement.Builder mappedStatementMerge;
        List<DynamicMappedStatement> children;
        if (mergeIndex >= 0) {
            DynamicMappedStatement dms = dmsList.get(mergeIndex);
            ;
            mappedStatementMerge = dms.toBuilder();
            children = dmsList.stream().filter(d -> d != dms).collect(Collectors.toList());
            dms.setChildren(children);
        } else {
            children = dmsList;
            mappedStatementMerge = new DynamicMappedStatement().toBuilder()
                    .setAuth(Boolean.TRUE)
                    .setName(namespace)
                    .setRest(Boolean.FALSE)
                    .setShortId(UUID.randomUUID().toString().replace("-", ""))
                    .setCommandType(CommandType.StandardCommand.MERGE)
                    .setChildren(dmsList);
        }
        if (CollectionUtils.isNotEmpty(children)) {
            children.stream().forEach(d -> d.setParentId(mappedStatementMerge.builder().getId()));
        }
        //合并出参和入参
        DynamicMixedMappedStatementFieldParser fieldParser = dynamicSqlSession.getDynamicMappedStatementHelper().getMixedMappedStatementFieldParser();
        MappedStatementMetaField inputParameter = new MappedStatementMetaField();
        inputParameter.setType(Type.StandardType.STRUCT.javaTypeAlias);
        MappedStatementMetaField outputParameter = new MappedStatementMetaField();
        outputParameter.setType(Type.StandardType.STRUCT.javaTypeAlias);

        dmsList.stream().forEach(dms -> {
            //合并入参
            List<MappedStatementMetaField> inputParameterList = BeanUtils.serializeCopy(dms.getInputParameter());
            if (CollectionUtils.isNotEmpty(inputParameterList)) {
                List<MappedStatementMetaField> slaveInputParameterList = TreeUtil.toTree(inputParameterList);
                for (MappedStatementMetaField slaveInputParameter : slaveInputParameterList) {
                    fieldParser.mergeTree(inputParameter, slaveInputParameter);
                }
            }
            List<MappedStatementMetaField> outputParameterList = BeanUtils.serializeCopy(dms.getOutputParameter());
            if (CollectionUtils.isNotEmpty(outputParameterList)) {
                List<MappedStatementMetaField> slaveOutputParameterList = TreeUtil.toTree(outputParameterList);
                for (MappedStatementMetaField slaveOutputParameter : slaveOutputParameterList) {
                    fieldParser.mergeTree(outputParameter, slaveOutputParameter);
                }
            }
        });
        //设置inputParameter 和 outputParameter
        if (mergeIndex < 0) {
            TreeUtil.setTree(inputParameter, TreeUtil.rootParentId, TreeUtil.parentIdKey, TreeUtil.idKey, TreeUtil.childrenKey);
            TreeUtil.setTree(outputParameter, TreeUtil.rootParentId, TreeUtil.parentIdKey, TreeUtil.idKey, TreeUtil.childrenKey);
        }
        mappedStatementMerge.setInputParameter(inputParameter).setOutputParameter(outputParameter);

        //将非select、insert、update、delete、reference标签添加到合并后的跟节点
        Element element = parserDom4jMapperBodyXml(sqlStatement, namespace);
        String otherTagXml = evalIgnoreNodes(element);
        mappedStatementMerge.setSqlStatement(otherTagXml);

        DynamicMappedStatement merge = mappedStatementMerge.builder();
        if (merge.getChildren().stream().allMatch(d -> RequestMethod.StandardRequestMethod.GET.name().equals(d.getMethod()))) {
            merge.setMethod(RequestMethod.StandardRequestMethod.GET);
        } else {
            merge.setMethod(RequestMethod.StandardRequestMethod.POST);
        }
        return mappedStatementMerge.builder();
    }

    public DynamicMappedStatementMixedResult validateExecute(boolean isTemporary, String tenantCode, String namespace, String sqlStatement, List<DynamicMappedStatement> dmsList) {

        String tempNamespace = NamespaceHelper.getRandomNamespace();
        DynamicMappedStatementMixedResult mixedResult = new DynamicMappedStatementMixedResult();
        DynamicConfiguration dynamicConfiguration = ((DynamicConfiguration) dynamicSqlSession.getSqlSession().getConfiguration());
        if (isTemporary) {
            namespace = tempNamespace;
            dynamicConfiguration.addTemporaryNamespace(NamespaceHelper.getNamespace(tenantCode,namespace));
        }
        resetDynamicMappedStatement(namespace, dmsList);
        List<DynamicMappedStatement> dmsCopyList = BeanUtils.serializeCopy(dmsList);
        DynamicMappedStatement root = dmsCopyList.stream().filter(dms -> dms.getTreeParentId() != null && dms.getTreeParentId() == 0).findFirst().orElse(null);
        List<DynamicMappedStatement> children = null;
        if (root != null && dmsCopyList.size() > 1) {
            children = dmsCopyList.stream().filter(dms -> Objects.equals(dms.getParentId(), root.getId())).collect(Collectors.toList());
            root.setChildren(children);
        }
        dmsCopyList = arrayToTree(dmsCopyList);
        if (CollectionUtils.isNotEmpty(children)) {
            dmsCopyList.addAll(children);
        }
        dynamicSqlSession.getDynamicMappedStatementHelper().addDynamicMappedStatement(dmsCopyList, !isTemporary);
        parseMapperMappedStatement(tenantCode,namespace,dmsCopyList.get(0).getShortId(),sqlStatement);
        //执行
        List<DynamicMappedStatementExecuteResult> results = new ArrayList<>();
        for (DynamicMappedStatement dms : dmsCopyList) {
            if (CollectionUtils.isNotEmpty(dms.getChildren())) {
                continue;
            }
            DynamicMappedStatementExecuteResult executeResult = executeDynamicMappedStatement(dms, dms.getInputParameterMock());
            results.add(executeResult);
        }
        mixedResult.setExecuteResults(results = TreeUtil.toArray(results, TreeUtil.childrenKey));
        if (isTemporary) {
            //删除临时namespace
            dynamicConfiguration.cleanTemporaryNamespace(tempNamespace);
        }
        //异常处理
        if (results.stream().anyMatch(r -> r.getStatus() != null && !r.getStatus())) {
            //删除已经生成MappedStatement
            List<DynamicMappedStatement> dms = results.stream().filter(r -> r.getMappedStatement() != null && StringUtils.isNotBlank(r.getMappedStatement().getSqlStatement())).map(DynamicMappedStatementExecuteResult::getMappedStatement).collect(Collectors.toList());
            dynamicConfiguration.cleanDynamicMappedStatement(dms);
            //错误提示
            String message = results.stream().filter(r -> r.getStatus() != null && !r.getStatus()).map(DynamicMappedStatementExecuteResult::getMessage).collect(Collectors.joining(System.lineSeparator()));
            mixedResult.setMessage(message);
            mixedResult.setStatus(Alert.StandardAlert.error);
        } else {
            String message = results.stream().filter(r -> r.getStatus() != null && r.getStatus() && StringUtils.isNotBlank(r.getMessage())).map(DynamicMappedStatementExecuteResult::getMessage).collect(Collectors.joining(System.lineSeparator()));
            mixedResult.setMessage(message);
            mixedResult.setStatus(Alert.StandardAlert.success);
        }
        return mixedResult;
    }

    public List<DynamicMappedStatement> resetDynamicMappedStatement(String namespace, List<DynamicMappedStatement> dmsList) {
        for (DynamicMappedStatement dms : dmsList) {
            dms.toBuilder().setNamespace(namespace).builder();
            if (CollectionUtils.isNotEmpty(dms.getChildren())) {
                resetDynamicMappedStatement(namespace, dms.getChildren());
            }
        }
        return dmsList;
    }

    public void copyIgnorePropertiesDynamicMappedStatement(List<DynamicMappedStatement> masterList, List<DynamicMappedStatement> slaveList) {
        if (CollectionUtils.isEmpty(slaveList) || CollectionUtils.isEmpty(masterList)) {
            return;
        }
        for (DynamicMappedStatement master : masterList) {
            DynamicMappedStatement slave = slaveList.stream().filter(d -> Objects.equals(master.getShortId(), d.getShortId())).findFirst().orElse(null);
            if (slave == null) {
                continue;
            }
          String [] names =   LambdaUtils.getMultipleFieldName(
                  DynamicMappedStatement::getTenantCode,DynamicMappedStatement::getNamespace,
                  DynamicMappedStatement::getChildren, DynamicMappedStatement::getRequestHeader,
                  DynamicMappedStatement::getInputParameter, DynamicMappedStatement::getOutputParameter
            ).stream().toArray(String[]::new);
            BeanUtils.copy(slave, master, names);
        }
    }

    public void copyDynamicMappedStatement(List<DynamicMappedStatement> masterList, List<DynamicMappedStatement> slaveList) {
        DynamicMixedMappedStatementFieldParser fieldParser = dynamicSqlSession.getDynamicMappedStatementHelper().getMixedMappedStatementFieldParser();
        if (CollectionUtils.isEmpty(slaveList) || CollectionUtils.isEmpty(masterList)) {
            return;
        }
        for (DynamicMappedStatement master : masterList) {
            DynamicMappedStatement slave = slaveList.stream().filter(d -> Objects.equals(master.getShortId(), d.getShortId())).findFirst().orElse(null);
            if (slave == null) {
                continue;
            }
            arrayToTree(slave);
            List<MappedStatementMetaField> masterRequestHeaderList = master.getRequestHeader();
            List<MappedStatementMetaField> masterInputParameterList = master.getInputParameter();
            List<MappedStatementMetaField> masterOutputParameterList = master.getOutputParameter();
            List<MappedStatementMetaField> slaveRequestHeaderList = slave.getRequestHeader();
            List<MappedStatementMetaField> slaveInputParameterList = slave.getInputParameter();
            List<MappedStatementMetaField> slaveOutputParameterList = slave.getOutputParameter();
            BeanUtils.copy(slave, master);

            if (CollectionUtils.isEmpty(master.getRequestHeader())) {
                master.setRequestHeader(slaveRequestHeaderList);
            } else if (CollectionUtils.isNotEmpty(masterRequestHeaderList) && CollectionUtils.isNotEmpty(slave.getRequestHeader())) {
                fieldParser.mergeTree(masterRequestHeaderList.get(0), slaveRequestHeaderList.get(0));
                master.setRequestHeader(masterRequestHeaderList);
            }

            if (CollectionUtils.isEmpty(master.getInputParameter())) {
                master.setInputParameter(slaveInputParameterList);
            } else if (CollectionUtils.isNotEmpty(slave.getInputParameter())) {
                fieldParser.mergeTree(masterInputParameterList.get(0), slaveInputParameterList.get(0));
                master.setInputParameter(masterInputParameterList);
            }
            if (CollectionUtils.isEmpty(master.getOutputParameter())) {
                master.setOutputParameter(slaveOutputParameterList);
            } else if (CollectionUtils.isNotEmpty(slave.getOutputParameter())) {
                fieldParser.mergeTree(masterOutputParameterList.get(0), slaveOutputParameterList.get(0));
                master.setOutputParameter(masterOutputParameterList);
            }
        }
        //将slaveList比masterList多出的添加到masterList中
        List<DynamicMappedStatement> dmsList = slaveList.stream().filter(s -> !masterList.stream().anyMatch(m -> Objects.equals(s.getShortId(), m.getShortId()))).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(dmsList)) {
            // masterList.addAll(dmsList);
        }
    }

    public DynamicMappedStatementExecuteResult executeDynamicMappedStatement(DynamicMappedStatement dms, Object parameter) {
        DynamicMappedStatementExecuteResult executeResult = new DynamicMappedStatementExecuteResult();
        //执行跟节点SQL
        if (StringUtils.isNotBlank(dms.getSqlStatement())) {
            try {
                Object result = dynamicSqlSession.executeTest(dms, parameter, dms.getTargetDataSourceKey());
                executeResult.setStatus(Boolean.TRUE);
                executeResult.setResult(result);
                executeResult.setMessage(dms.getShortId() + " 执行成功. ");
            } catch (Exception e) {
                String message = dms.getShortId() + " 执行失败. " + e.getMessage();
                MyBatisExecutorException exception = new MyBatisExecutorException(message, e.getCause());
                e.printStackTrace();
                executeResult.setResult(ExceptionUtils.getStackTrace(exception));
                executeResult.setMessage(exception.getMessage());
                executeResult.setStatus(Boolean.FALSE);
            }
            executeResult.setMappedStatement(dms);
        } else {
            executeResult.setStatus(Boolean.TRUE);
            executeResult.setResult(new HashMap<>());
        }
        //执行子节点SQL
        if (CollectionUtils.isNotEmpty(dms.getChildren())) {
            executeResult.setChildren(new ArrayList<>());
            for (DynamicMappedStatement child : dms.getChildren()) {
                DynamicMappedStatementExecuteResult childResult = executeDynamicMappedStatement(child, parameter);
                executeResult.getChildren().add(childResult);
                executeResult.setResult(BeanUtils.copy(childResult.getResult(), executeResult.getResult()));
            }
        }
        return executeResult;
    }

    public List<DynamicMappedStatement> treeToArray(List<DynamicMappedStatement> dmsList, boolean setTree) {
        //dm转换
        TreeUtil.setTree(dmsList, 0, "treeParentId", "treeId", "children");
        List<DynamicMappedStatement> dmsArray = TreeUtil.toArray(dmsList, "children");
        for (DynamicMappedStatement dms : dmsArray) {
            List<MappedStatementMetaField> inputParameters;
            List<MappedStatementMetaField> outputParameters;
            if (setTree) {
                inputParameters = TreeUtil.setTree(dms.getInputParameter());
                outputParameters = TreeUtil.setTree(dms.getOutputParameter());
            } else {
                inputParameters = dms.getInputParameter();
                outputParameters = dms.getOutputParameter();
            }
            List<MappedStatementMetaField> inputParameter = TreeUtil.toArray(inputParameters, "children");
            List<MappedStatementMetaField> outputParameter = TreeUtil.toArray(outputParameters, "children");
            dms.toBuilder().setInputParameter(inputParameter).setOutputParameter(outputParameter);
        }
        return dmsArray;
    }

    public List<DynamicMappedStatement> arrayToTree(List<DynamicMappedStatement> dmsList) {
        if (CollectionUtils.isEmpty(dmsList)) {
            return Collections.EMPTY_LIST;
        }
        dmsList = TreeUtil.toTree(dmsList, 0, "treeParentId", "treeId", "children");
        for (DynamicMappedStatement dms : dmsList) {
            arrayToTree(dms);
        }
        return dmsList;
    }

    public DynamicMappedStatement arrayToTree(DynamicMappedStatement dms) {
        if (dms == null) {
            return null;
        }
        List<MappedStatementMetaField> inputParameters = TreeUtil.toTree(dms.getInputParameter(), TreeUtil.rootParentId, TreeUtil.parentIdKey, TreeUtil.idKey, TreeUtil.childrenKey);
        if (CollectionUtils.isNotEmpty(inputParameters)) {
            dms.setInputParameter(inputParameters);
        }
        List<MappedStatementMetaField> outputParameters = TreeUtil.toTree(dms.getOutputParameter(), TreeUtil.rootParentId, TreeUtil.parentIdKey, TreeUtil.idKey, TreeUtil.childrenKey);
        if (CollectionUtils.isNotEmpty(outputParameters)) {
            dms.setOutputParameter(outputParameters);
        }
        if (CollectionUtils.isNotEmpty(dms.getChildren())) {
            for (DynamicMappedStatement child : dms.getChildren()) {
                arrayToTree(child);
            }
        }
        return dms;
    }
}